package edu.cuit.zhuyimeng.uaa.security;

import cn.dev33.satoken.stp.StpInterface;
import com.alicp.jetcache.anno.Cached;
import com.baomidou.dynamic.datasource.annotation.Slave;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import edu.cuit.zhuyimeng.uaa.dal.po.*;
import edu.cuit.zhuyimeng.uaa.dal.mapper.PermMapper;
import edu.cuit.zhuyimeng.uaa.dal.mapper.RoleMapper;
import edu.cuit.zhuyimeng.uaa.enums.CacheConstants;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 鉴权实现类
 */
@Component
@RequiredArgsConstructor
public class StpInterfaceImpl implements StpInterface {

    //导入所有mapper包下的类
    private final RoleMapper roleMapper;
    private final PermMapper permMapper;

    @Override
    @Slave
    @Cached(name = CacheConstants.PERM_CACHE, key = "args[0]")
    public List<String> getPermissionList(Object loginId, String loginType) {

//        List<String> roles = StpUtil.getRoleList();
        List<String> roles = getRoleList(loginId, loginType);

        List<String> permissions = permMapper.selectJoinList(PermPO.class, new MPJLambdaWrapper<PermPO>()
                .select(PermPO::getName, PermPO::getId)
                .leftJoin(RolePO.class, on -> on
                        .in(RolePO::getName, roles))
                .leftJoin(RolePermPO.class, on -> on
                        .eq(RolePO::getId, RolePermPO::getRoleId))
                .eq(PermPO::getId, RolePermPO::getPermId)
                .distinct()
        ).stream().map(PermPO::getName).toList();

        return permissions;
    }

    @Override
    @Slave
    @Cached(name = CacheConstants.ROLE_CACHE, key = "args[0]")
    public List<String> getRoleList(Object loginId, String loginType) {

        List<String> roles = new ArrayList<>();

        RolePO originRole = roleMapper.selectJoinOne(RolePO.class, new MPJLambdaWrapper<RolePO>()
                .select(RolePO::getName, RolePO::getInheritId, RolePO::getId)
                .leftJoin(UserPO.class, on -> on
                        .eq(UserPO::getName, loginId))
                .leftJoin(UserRolePO.class, on -> on
                        .eq(UserPO::getId, UserRolePO::getUserId))
                .eq(RolePO::getId, UserRolePO::getRoleId)
        );

        if (originRole == null) {
            roles.add("user");
        } else {
            roles.add(originRole.getName());
        }

        if (originRole.getInheritId() != null) {
            fillSubRoles(originRole.getInheritId(), roles);
        }

        return roles;
    }

    /**
     * 获取角色所有子角色
     *
     * @param inheritId 继承角色的id
     */
    private void fillSubRoles(int inheritId, List<String> roleList) {
        LambdaQueryWrapper<RolePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(RolePO::getInheritId, RolePO::getId, RolePO::getName).eq(RolePO::getId, inheritId);
        RolePO role = roleMapper.selectOne(queryWrapper);
        roleList.add(role.getName());
        if (role.getInheritId() != null) {
            fillSubRoles(role.getInheritId(), roleList);
        }
    }
}
